# -*- coding: utf-8 -*-
"""
场景生成步骤
根据解析的Markdown内容生成Manim场景
"""

import json
import logging
from pathlib import Path
from typing import Dict, Any, List, Optional

from ..step_base import BaseStep, StepResult
from ...animation.templates import (
    TextSceneTemplate,
    TitleSceneTemplate,
    MathSceneTemplate,
    CodeSceneTemplate,
)

logger = logging.getLogger(__name__)


class GenerateScenesStep(BaseStep):
    """场景生成步骤"""

    name = "generate_scenes"
    description = "生成Manim场景代码"
    required_inputs = ["scene_list"]
    optional_inputs = ["theme", "style_config"]
    produces_outputs = ["scene_files", "animation_config"]

    def __init__(
        self,
        output_dir: Path,
        scene_list: Optional[List[Dict[str, Any]]] = None,
        theme: str = "dark",
        **kwargs,
    ):
        """
        初始化步骤

        Args:
            output_dir: 输出目录
            scene_list: 场景列表
            theme: 主题
        """
        super().__init__(output_dir, **kwargs)
        self.scene_list = scene_list
        self.theme = theme
        self.style_config = {}

    def validate_inputs(self) -> tuple[bool, list[str]]:
        """验证输入"""
        errors = []

        if not self.scene_list:
            errors.append("No scene list provided")

        if not isinstance(self.scene_list, list):
            errors.append("Scene list must be a list")

        return len(errors) == 0, errors

    def run(self) -> StepResult:
        """执行步骤"""
        try:
            self.report_progress(0, "Loading scene list")

            # 生成场景
            self.report_progress(30, "Generating scenes")

            scene_files = []
            animation_configs = []

            for i, scene_data in enumerate(self.scene_list):
                self.report_progress(
                    30 + (i / len(self.scene_list)) * 50,
                    f"Generating scene {i+1}/{len(self.scene_list)}: {scene_data.get('title', 'Untitled')}"
                )

                scene_file = self._generate_scene_file(scene_data, i)
                scene_files.append(scene_file)

                # 生成动画配置
                config = self._generate_animation_config(scene_data)
                animation_configs.append(config)

            # 保存配置
            self.report_progress(85, "Saving animation configurations")

            self._save_configs(scene_files, animation_configs)

            # 完成
            self.report_progress(100, "Scenes generated successfully")

            return StepResult(
                success=True,
                message="Scenes generated successfully",
                data={
                    "total_scenes": len(self.scene_list),
                    "scene_files": scene_files,
                    "theme": self.theme,
                },
                output_files=[
                    self.output_dir / "scenes.json",
                    self.output_dir / "animation_configs.json",
                ],
            )

        except Exception as e:
            logger.exception("Failed to generate scenes")
            return StepResult(
                success=False,
                message=f"Failed to generate scenes: {str(e)}",
            )

    def _generate_scene_file(self, scene_data: Dict[str, Any], index: int) -> Path:
        """
        生成场景文件

        Args:
            scene_data: 场景数据
            index: 场景索引

        Returns:
            场景文件路径
        """
        scene_type = scene_data.get("type", "text")
        scene_name = f"scene_{index:03d}_{scene_type}"

        # 根据类型创建不同的模板
        if scene_type == "title":
            template = TitleSceneTemplate(
                title=scene_data.get("title", ""),
                subtitle=scene_data.get("subtitle", ""),
                theme=self.theme,
            )
        elif scene_type == "math":
            # 查找数学公式
            math_content = self._extract_math_content(scene_data)
            template = MathSceneTemplate(
                title=scene_data.get("title", ""),
                formula=math_content.get("formula", ""),
                explanation=math_content.get("explanation", ""),
                theme=self.theme,
            )
        elif scene_type == "code":
            # 查找代码
            code_content = self._extract_code_content(scene_data)
            template = CodeSceneTemplate(
                title=scene_data.get("title", ""),
                code=code_content.get("content", ""),
                language=code_content.get("language", "python"),
                theme=self.theme,
            )
        else:
            # 文本场景
            content_text = self._extract_text_content(scene_data)
            template = TextSceneTemplate(
                title=scene_data.get("title", ""),
                text=content_text,
                theme=self.theme,
            )

        # 生成Python代码
        scene_code = self._generate_scene_code(template, scene_name)

        # 保存文件
        scene_file = self.output_dir / f"{scene_name}.py"
        with open(scene_file, "w", encoding="utf-8") as f:
            f.write(scene_code)

        return scene_file

    def _extract_math_content(self, scene_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        提取数学内容

        Args:
            scene_data: 场景数据

        Returns:
            数学内容
        """
        formula = ""
        explanation = ""

        # 从内容中查找LaTeX公式
        for item in scene_data.get("content", []):
            if isinstance(item, str):
                # 检查是否包含LaTeX
                if "$" in item:
                    formula = item
            elif isinstance(item, dict) and item.get("type") == "text":
                if "$" in item.get("text", ""):
                    formula = item["text"]

        return {"formula": formula, "explanation": explanation}

    def _extract_code_content(self, scene_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        提取代码内容

        Args:
            scene_data: 场景数据

        Returns:
            代码内容
        """
        code_content = ""
        language = "python"

        for item in scene_data.get("content", []):
            if isinstance(item, dict):
                if item.get("type") == "code":
                    code_content = item.get("content", "")
                    language = item.get("language", "python")
                    break

        return {"content": code_content, "language": language}

    def _extract_text_content(self, scene_data: Dict[str, Any]) -> str:
        """
        提取文本内容

        Args:
            scene_data: 场景数据

        Returns:
            文本内容
        """
        text_lines = []

        for item in scene_data.get("content", []):
            if isinstance(item, str):
                text_lines.append(item)
            elif isinstance(item, dict):
                if item.get("type") == "text":
                    text_lines.append(item.get("text", ""))
                elif item.get("type") == "list":
                    text_lines.append(f"• {item.get('text', '')}")

        return "\n".join(text_lines)

    def _generate_scene_code(self, template, scene_name: str) -> str:
        """
        生成场景代码

        Args:
            template: 场景模板
            scene_name: 场景名称

        Returns:
            Python代码
        """
        # 生成场景类
        class_name = scene_name.replace("_", " ").title().replace(" ", "")

        code = f'''# -*- coding: utf-8 -*-
"""
自动生成的场景: {scene_name}
"""

from manim import *
from pathlib import Path

class {class_name}(Scene):
    """{template.description if hasattr(template, 'description') else 'Generated scene'}"""

    def construct(self):
        """构建场景"""
        # 初始化模板
        template = {template.__class__.__name__}(
            title={repr(template.title) if hasattr(template, 'title') else "''"},
            theme="{self.theme}",
        )

        # 创建内容
        content = template.create_content(self)

        # 动画内容
        template.animate_content(self, content)
'''

        return code

    def _generate_animation_config(self, scene_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        生成动画配置

        Args:
            scene_data: 场景数据

        Returns:
            动画配置
        """
        scene_type = scene_data.get("type", "text")

        # 基础配置
        config = {
            "scene_type": scene_type,
            "order": scene_data.get("order", 0),
            "duration": 5.0,  # 默认5秒
            "animations": [],
        }

        # 根据类型调整配置
        if scene_type == "title":
            config["duration"] = 3.0
            config["animations"] = [
                {"type": "scale_in", "duration": 1.0},
            ]
        elif scene_type == "math":
            config["duration"] = 7.0
            config["animations"] = [
                {"type": "write", "duration": 2.0},
            ]
        elif scene_type == "code":
            config["duration"] = 10.0
            config["animations"] = [
                {"type": "fade_in_line", "duration": 0.2, "repeat": True},
            ]
        else:
            config["duration"] = 5.0
            config["animations"] = [
                {"type": "write", "duration": 1.5},
            ]

        return config

    def _save_configs(self, scene_files: List[Path], animation_configs: List[Dict[str, Any]]):
        """
        保存配置

        Args:
            scene_files: 场景文件列表
            animation_configs: 动画配置列表
        """
        # 保存场景文件列表
        scenes_data = {
            "total_scenes": len(scene_files),
            "scene_files": [str(f) for f in scene_files],
            "theme": self.theme,
        }

        with open(self.output_dir / "scenes.json", "w", encoding="utf-8") as f:
            json.dump(scenes_data, f, indent=2, ensure_ascii=False)

        # 保存动画配置
        with open(self.output_dir / "animation_configs.json", "w", encoding="utf-8") as f:
            json.dump(animation_configs, f, indent=2, ensure_ascii=False)
